extern crate encoding;

mod email;
mod db;
use async_std::{net::TcpStream, stream::StreamExt};
use chrono::{DateTime, Utc};
use db::users::Users;
use email::{batch_email, get_email_body, get_email_body_once};
use lettre::{message::header::ContentType, transport::smtp::authentication::Credentials, Message, SmtpTransport, Transport};
use mailparse::{parse_mail, MailHeaderMap};
use reqwest::Client;
use serde::{Deserialize, Serialize};
use tauri::Manager;
use tauri_plugin_dialog::DialogExt;

#[derive(Debug,Serialize,Deserialize)]
pub struct Data<T>{
    status: i64,
    msg: String,
    datas: Vec<T>,
}

#[tauri::command]
async fn login(userid:String,password:String) -> Data<()>{
    let new_user = Users::new(&userid, "", &password).await;
    let mut msg = String::new();
    
    msg.push_str("OK,");
    msg.push_str(&userid);
    msg.push_str(&password);

    Data{
        status: 200,
        msg,
        datas: Vec::new()
    }
}

#[tauri::command]
async fn get_login_users() -> Vec<db::users::Users>{
    //let mut users: Vec<db::users::Users> = Vec::new();
    let users = db::users::get_loin_users().await.unwrap();
    
    //users.append(&mut login_users);
    users
}
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
#[tauri::command]
fn greet(name: &str) -> String {
    format!("Hello, {}! You've been greeted from Rust!", name)
}

#[tauri::command]
fn close_window(app: tauri::AppHandle) {
    //let main_window = app.get_webview_window("main").unwrap();
    std::thread::spawn(move || {
        let answer = app.dialog().message("确定退出吗？").title("确认")
        .kind(tauri_plugin_dialog::MessageDialogKind::Warning).buttons(tauri_plugin_dialog::MessageDialogButtons::YesNo)
        .blocking_show();
        if answer {
            println!("quit");
            app.exit(0);
        }else {
            println!("cancel");
            return;
        }
    }); 
}
#[tauri::command]
fn max_window(app: tauri::AppHandle){
    let main_window = app.get_webview_window("main").unwrap();
    if main_window.is_maximized().unwrap() {
        main_window.unmaximize().unwrap();
    }else {
        main_window.maximize().unwrap();    
    }
    
}

#[tauri::command]
fn min_window(app: tauri::AppHandle){
    let main_window = app.get_webview_window("main").unwrap();
    
    main_window.minimize().unwrap();
    
}

#[derive(Debug,Serialize,Deserialize)]
struct Response {
    from:Option<String>,
    to:Option<String>,
    tgt_text:Option<String>,
    src_text:Option<String>,
    error_code:Option<String>,
    error_msg:Option<String>,
}

#[tauri::command]
async fn requst(from:String,to:String,text:String) -> Response{
    let client = Client::new();
    let api_key = "aba83ca70a7f61b0eff20fc5b5ea6b9d";

    let url = format!("https://api.niutrans.com/NiuTransServer/translation?from={}&to={}&apikey={}&src_text={}"
        ,from,to,api_key,urlencoding::encode(text.as_str()));
    let result = client.get(url)
        .header("Content-Type","application/x-www-form-urlencoded; charset=utf-8")
        .send().await.unwrap();
    let resp = result.json::<Response>().await.unwrap();
    resp

}

#[tauri::command]
fn send_email(){
    let email = Message::builder()
        .from("zenghaifenghandsom@163.com".parse().unwrap())
        .reply_to("zenghaifenghandsome@gmail.com".parse().unwrap())
        .to("zenghaifenghandsome@gmail.com".parse().unwrap())
        .subject("good morning")
        .header(ContentType::TEXT_PLAIN)
        .body(String::from("this is an email for test !!!")).unwrap();

    let creds = Credentials::new("zenghaifenghandsom@163.com".to_owned(), "QDunvLP8Vrnhn5hJ".to_owned());

    let mailer = SmtpTransport::relay("smtp.163.com").unwrap().credentials(creds).build();

    match mailer.send(&email) {
        Ok(_) => println!("email send successfull"),
        Err(e) => panic!("could not send email:{e:?}"),
    }
}

#[derive(Debug,Serialize,Deserialize,Clone)]
struct EmailHeader {
    id : u32,
    from:Option<String>,
    to:Option<String>,
    subject:Option<String>,
    date:Option<String>,
    num:u32,
}
impl EmailHeader {
    pub fn new(id:u32,num:u32) -> Self{
        EmailHeader{
            id,
            from:None,
            to:None,
            subject:None,
            date:None,
            num,
        }
    }
}
#[tauri::command]
async fn get_email_list() -> Vec<EmailHeader>{
    let mut email_list:Vec<EmailHeader> = Vec::new();
    let server = ("imap.163.com",993);
    let tcp = TcpStream::connect(server).await.unwrap();
    let tls = async_native_tls::TlsConnector::new();
    let tls_stream = tls.connect("imap.163.com", tcp).await.unwrap();
    let client = async_imap::Client::new(tls_stream);

    let mut session = client.login("zenghaifenghandsom@163.com", "QDunvLP8Vrnhn5hJ").await.unwrap();
    
    //let mut session = client.login("zenghaifenghandsom@163.com", "QDunvLP8Vrnhn5hJ").unwrap();
    //session.read_greeting().unwrap();
    //ID name zenghaifeng" "version" "1.0.0" "vendor" "myclient" "support-email" "zenghaifenghandsom@163.com")
    // ID ("name" "zenghaifeng" "version" "1.0.0" "vendor" "myclient" "support-email" "zenghaifenghandsom@163.com")
    let idstr = vec!(("name", Some("zenghaifeng")),("version", Some("1.0.0")),("vendor", Some("myclient")),("support-email", Some("zenghaifenghandsom@163.com"))); // (, ,, );
    
    session.id(idstr).await.unwrap();

    let s = session.select("inbox").await.unwrap();

    let num = s.exists;
    //println!("{}",s.exists);
    for i in 1..=num {

        let mut email_header = EmailHeader::new(i,num);
        let ms = session.fetch(format!("{i}"), "BODY[HEADER.FIELDS (FROM TO DATE SUBJECT)]").await.unwrap();

        let mes:Vec<_> = ms.collect().await;
        // println!("{:#?}",mes);
        let me = mes.first().unwrap().as_ref().unwrap();
        
        // println!("{:?}",h);
        let bd = me.header().unwrap();

        let ps = parse_mail(bd).unwrap();

        let subject = ps.headers.get_first_value("Subject").unwrap();
        let from = ps.headers.get_first_value("From").unwrap();
        let to = ps.headers.get_first_value("To").unwrap();
        let date = ps.headers.get_first_value("Date").unwrap();
        let date:Vec<_> = date.split("(").collect();
        let date = date.get(0).unwrap().trim();
        //println!("{date}");
        let date = DateTime::parse_from_str(&date,"%a, %d %b %Y %H:%M:%S %z").unwrap();

        let date = date.with_timezone(&Utc).format("%Y-%m-%d").to_string();

        email_header.subject=Some(subject);
        email_header.from=Some(from);
        email_header.to=Some(to);
        email_header.date=Some(date);

        //println!("{:#?}",email_header);
        email_list.push(email_header);
        
    }
    session.logout().await.unwrap();
    return email_list;

}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_dialog::init())
        .plugin(tauri_plugin_shell::init())
        .invoke_handler(tauri::generate_handler![greet, close_window,max_window,min_window,
            requst,send_email,get_email_list,batch_email,get_email_body,get_email_body_once,get_login_users,login])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

#[tokio::test]
async fn test() {
    let result = requst("zh".to_string(), "en".to_string(), "早上".to_string()).await;
    println!("{:#?}",result);
}

#[test]
fn test1(){
    send_email();
}

#[tokio::test]
async fn test_get_emails(){
    get_email_list().await;
}

#[test]
fn date_test(){

    let date = "Sun, 2 Jul 2023 14:44:18 +0800";//"Fri, 20 Dec 2024 14:54:43 -0800"; %a, %d %b %Y %H:%M:%S %z
    let date = DateTime::parse_from_str(&date,"%a, %d %b %Y %H:%M:%S %z").unwrap();

    let date = date.with_timezone(&Utc).format("%Y-%m-%d").to_string();

    println!("{date}");
}